#ifndef __DLIST_H__
#define __DLIST_H__

static void* mem_zalloc(size_t size)
{
	void* p = malloc(size);
	if (p)
		memset(p, 0, size);
	return p;
}

// 定义一个双链表结构
#define DLIST_DEFINE(TYPE, _DEFINE) \
	TYPE { _DEFINE; TYPE* prev; TYPE* next; };

#define DLIST_NEW_OBJECT(TYPE, node) \
    (node = (TYPE*)mem_zalloc(sizeof(TYPE)))

#define DLIST_ADD(_root, _node)   {\
    _node->prev = NULL; _node->next = _root; \
    if (_root) { _root->prev = _node; } \
    _root = _node; \
}

#define DLIST_ADD_TAIL(TYPE, _root, _node)   {\
	if (_root) { \
		TYPE* temp = _root; \
		while (temp && temp->next) temp = temp->next; \
		temp->next = _node; \
		_node->prev = temp; \
	} \
	else \
		_root = _node; \
}

#define DLIST_REMOVE(_root, _node) { \
    if (_node->prev) { \
        _node->prev->next = _node->next; \
        if (_node->next) \
            _node->next->prev = _node->prev; \
    } \
    else { \
        _root = _node->next;  \
        if (_root)   \
            _root->prev = NULL; \
    } \
}

#define DLIST_FREE(_root, _node) \
    { DLIST_REMOVE(_root, _node); free(_node); }

// 按指定参数的值由小到大排序
#define DLIST_INSERT_INT(TYPE, _root, _node, comp_key) \
    { \
        TYPE* next = _root, *prev = NULL; \
        while (next) { \
            if (next->comp_key > _node->comp_key) \
                break; \
            prev = next; next = next->next; \
        } \
        _node->next = next; \
        if (next) next->prev = _node; \
        if (prev) { \
            prev->next = _node; _node->prev = prev; \
        } else \
            _root = _node; \
    }


#define DLIST_FOR_EACH(TYPE, _root, node, CODE) \
	{ \
		TYPE* node = _root; \
		while (node) { \
			CODE; \
			node = node->next; \
		} \
	}

#define DLIST_FOR_EACH_AND_FREE(TYPE, _root, node, CODE) \
	{ \
		TYPE* node; \
		while ((node = _root)) { \
			CODE; \
            _root = _root->next; \
            if (_root) _root->prev = NULL; \
            free(node); \
		} \
	}

#define DLIST_FREE_ALL(TYPE, _root) \
    { \
        while (_root) { \
            TYPE* node = _root; \
            _root = _root->next; \
            free(node); \
        } \
    }

#endif

